﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace QldtSdh.BLL
{
    using DAL;
    using DAL.Models;

    class BizCongViecBanCuaGiangVien
    {
        internal static List<CongViecBanGiangVien> GetListMucNoiDungBan(GiangVien cuaGiangVien, HocKy trongHocKy, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext())
                    return GetListMucNoiDungBan(cuaGiangVien, trongHocKy, db2);
            else
            {
                if (cuaGiangVien == null || trongHocKy == null)
                    return null;
                var maGiangVien = cuaGiangVien.MaGiangVien;
                var maHocKyGUID = trongHocKy.MaHocKyGUID;
                var lst = db.CongViecBanGiangVienDbSet.Where(e => e.MaGiangVien == maGiangVien && e.MaHocKyGUID == maHocKyGUID)
                    .OrderBy(e => e.TuNgay)
                    .ThenBy(e => e.ThuTrongTuan)
                    .ThenBy(e => e.Buoi)
                    .ThenBy(e => e.DenNgay)
                    .ToList();
                return lst;
            }
        }

        static DateTime minOf(DateTime d1, DateTime d2)
        {
            return (d1 >= d2) ? d2 : d1;
        }

        static DateTime maxOf(DateTime d1, DateTime d2)
        {
            return (d1 >= d2) ? d1 : d2;
        }

        internal static void Insert(string maGiangVien, string maHocKyGUID, DateTime tuNgay, DateTime denNgay, int buoi, int thuTrongTuan, string noiDungBan, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext())
                    Insert(maGiangVien, maHocKyGUID, tuNgay, denNgay, buoi, thuTrongTuan, noiDungBan, db2);
            else
            {
                if (buoi < 0 || buoi > CongViecBanGiangVien.CảNgày)
                    throw new Exception("Dữ liệu buổi bận không hợp lệ");
                if (thuTrongTuan < 0 || thuTrongTuan > CongViecBanGiangVien.CácThứTrongTuần)
                    throw new Exception("Dữ liệu thứ trong tuần không hợp lệ");

                var x = new CongViecBanGiangVien()
                {
                    CongViecBanGiangVienGUID = System.Guid.NewGuid().ToString(),
                    MaGiangVien = maGiangVien,
                    MaHocKyGUID = maHocKyGUID,
                    TuNgay = tuNgay,
                    DenNgay = denNgay,
                    Buoi = buoi,
                    ThuTrongTuan = thuTrongTuan,
                    NoiDungBan = noiDungBan
                };

                #region Kiểm tra xem giảng viên có bận trong khoảng thời gian định thêm mới không?
                // Dạng 1
                var lstCongViecBan = db.CongViecBanGiangVienDbSet.Where(e => e.MaGiangVien == maGiangVien && e.MaHocKyGUID == maHocKyGUID &&
                            e.TuNgay <= tuNgay && tuNgay <= e.DenNgay).ToList();
                foreach (var congViecBan in lstCongViecBan)
                {
                    // Kiểm tra xem (buoi, thuTrongTuan trong khoảng [tuNgay, denNgay] có xung đột với congViecBan hay không
                    var denNgay2 = minOf(denNgay, congViecBan.DenNgay);
                    for (DateTime date = tuNgay; date <= denNgay2; date = date.AddDays(1))
                    {
                        if ((((byte)congViecBan.ThuTrongTuan & (byte)x.ThuTrongTuan) > 0) && (((byte)congViecBan.Buoi & (byte)x.Buoi) > 0))
                            throw new Exception(string.Format("Giảng viên bận {0} vào {1} trong {2}",
                                congViecBan.NoiDungBan, congViecBan.ThứTrongTuầnString, congViecBan.KhoảngThờiGianString));
                    }
                }

                // Dạng 2
                lstCongViecBan = db.CongViecBanGiangVienDbSet.Where(e => e.MaGiangVien == maGiangVien && e.MaHocKyGUID == maHocKyGUID &&
                    tuNgay <= e.TuNgay && e.DenNgay <= denNgay).ToList();
                foreach (var congViecBan in lstCongViecBan)
                {
                    // Kiểm tra xem (buoi, thuTrongTuan trong khoảng [tuNgay, denNgay] có xung đột với congViecBan hay không
                    for (DateTime date = congViecBan.TuNgay; date <= congViecBan.DenNgay; date = date.AddDays(1))
                    {
                        if ((((byte)congViecBan.ThuTrongTuan & (byte)x.ThuTrongTuan) > 0) && (((byte)congViecBan.Buoi & (byte)x.Buoi) > 0))
                            throw new Exception(string.Format("Giảng viên bận {0} vào {1} trong {2}",
                                congViecBan.NoiDungBan, congViecBan.ThứTrongTuầnString, congViecBan.KhoảngThờiGianString));
                    }
                }

                // Dạng 3
                lstCongViecBan = db.CongViecBanGiangVienDbSet.Where(e => e.MaGiangVien == maGiangVien && e.MaHocKyGUID == maHocKyGUID &&
                    e.TuNgay <= denNgay && denNgay <= e.DenNgay).ToList();
                foreach (var congViecBan in lstCongViecBan)
                {
                    // Kiểm tra xem (buoi, thuTrongTuan trong khoảng [tuNgay, denNgay] có xung đột với congViecBan hay không
                    var tuNgay2 = maxOf(tuNgay, congViecBan.TuNgay);
                    for (DateTime date = tuNgay2; date <= denNgay; date = date.AddDays(1))
                    {
                        if ((((byte)congViecBan.ThuTrongTuan & (byte)x.ThuTrongTuan) > 0) && (((byte)congViecBan.Buoi & (byte)x.Buoi) > 0))
                            throw new Exception(string.Format("Giảng viên bận {0} vào {1} trong {2}",
                                congViecBan.NoiDungBan, congViecBan.ThứTrongTuầnString, congViecBan.KhoảngThờiGianString));
                    }
                }
                #endregion

                #region Kiểm tra xem giảng viên có bận giảng dạy SĐH trong khoảng thời gian định thêm mới không?
                var lstTKB = db.LopHocPhan_ThoiKhoaBieuDbSet.Where(e => e.MaGiangVien == maGiangVien && tuNgay <= e.NgayHoc && e.NgayHoc <= denNgay).ToList();
                foreach (var tkb in lstTKB)
                {
                    var iThuTrongTuan = 1 << (byte)BizThoiKhoaBieu.GetIndexFromDOW(tkb.NgayHoc.DayOfWeek);
                    var iBuoiHoc = 1 << (byte)tkb.BuoiHoc;
                    var lhp = BizLopHocPhan.GetByID(tkb.MaLopHocPhanGUID);
                    if (((byte)x.ThuTrongTuan & iThuTrongTuan) > 0 && ((byte)x.Buoi & iBuoiHoc) > 0)
                        throw new Exception(string.Format("Giảng viên bận dạy SĐH vào {0} {1} ngày {2} (lớp {3})",
                            BizThoiKhoaBieu.GetStringOfBuoi(tkb.BuoiHoc),
                            BizThoiKhoaBieu.GetThuTrongTuan(tkb.NgayHoc), tkb.NgayHoc.ToString("dd/MM/yyyy"), lhp.TenLopHocPhan));
                }
                #endregion

                #region Kiểm tra xem giảng viên có bận giảng dạy ĐH trong khoảng thời gian định thêm mới không?
                try
                {
                    using (var db2 = CEMS_DHKH.Models.CEMS_DHKhoaHocContext.GetContext())
                    {
                        var lstTKB2 = db2.ThoiKhoaBieuDaoTaoDaiHocDbSet.Where(e => e.MaGiangVien == maGiangVien && tuNgay <= e.NgayHoc && e.NgayHoc <= denNgay).ToList();
                        foreach (var tkb in lstTKB)
                        {
                            var iThuTrongTuan = 1 << (byte)BizThoiKhoaBieu.GetIndexFromDOW(tkb.NgayHoc.DayOfWeek);
                            var iBuoiHoc = 1 << (byte)tkb.BuoiHoc;
                            if (((byte)x.ThuTrongTuan & iThuTrongTuan) > 0 && ((byte)x.Buoi & iBuoiHoc) > 0)
                                throw new Exception(string.Format("Giảng viên bận dạy ĐH vào {0} {1} ngày {2}",
                                    BizThoiKhoaBieu.GetStringOfBuoi(tkb.BuoiHoc),
                                    BizThoiKhoaBieu.GetThuTrongTuan(tkb.NgayHoc), tkb.NgayHoc.ToString("dd/MM/yyyy")));
                        }
                    }
                }
                catch { }
                #endregion

                db.CongViecBanGiangVienDbSet.Add(x);
                BizNhatKyHoatDong.LogAndCommitInsert2(x, x.CongViecBanGiangVienGUID, LOAIDOITUONG.CÔNG_VIỆC_BẬN_CỦA_GV, db);
            }
        }

        internal static void Update(string congViecBanGiangVienGUID, string maGiangVien, string maHocKyGUID, DateTime tuNgay, DateTime denNgay, int buoi, int thuTrongTuan, string noiDungBan, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext())
                    Update(congViecBanGiangVienGUID, maGiangVien, maHocKyGUID, tuNgay, denNgay, buoi, thuTrongTuan, noiDungBan, db2);
            else
            {
                var x = db.CongViecBanGiangVienDbSet.Where(e => e.CongViecBanGiangVienGUID == congViecBanGiangVienGUID).FirstOrDefault();
                if (x == null)
                    throw new Exception("Mục công việc bận của giảng viên không còn tồn tại trên hệ thống");

                if (buoi < 0 || buoi > CongViecBanGiangVien.CảNgày)
                    throw new Exception("Dữ liệu buổi bận không hợp lệ");
                if (thuTrongTuan < 0 || thuTrongTuan > CongViecBanGiangVien.CácThứTrongTuần)
                    throw new Exception("Dữ liệu thứ trong tuần không hợp lệ");

                var oldX = new CongViecBanGiangVien()
                {
                    CongViecBanGiangVienGUID = x.CongViecBanGiangVienGUID,
                    MaGiangVien = x.MaGiangVien,
                    TuNgay = x.TuNgay,
                    DenNgay = x.DenNgay,
                    Buoi = x.Buoi,
                    ThuTrongTuan = x.ThuTrongTuan,
                    NoiDungBan = x.NoiDungBan
                };
                x.MaGiangVien = maGiangVien;
                x.MaHocKyGUID = maHocKyGUID;
                x.TuNgay = tuNgay;
                x.DenNgay = denNgay;
                x.Buoi = buoi;
                x.ThuTrongTuan = thuTrongTuan;
                x.NoiDungBan = noiDungBan;

                #region Kiểm tra xem giảng viên có bận trong khoảng thời gian định thêm mới không?
                // Dạng 1
                var lstCongViecBan = db.CongViecBanGiangVienDbSet.Where(e => e.MaGiangVien == maGiangVien && e.MaHocKyGUID == maHocKyGUID &&
                            e.TuNgay <= tuNgay && tuNgay <= e.DenNgay && e.CongViecBanGiangVienGUID != congViecBanGiangVienGUID).ToList();
                foreach (var congViecBan in lstCongViecBan)
                {
                    // Kiểm tra xem (buoi, thuTrongTuan trong khoảng [tuNgay, denNgay] có xung đột với congViecBan hay không
                    var denNgay2 = minOf(denNgay, congViecBan.DenNgay);
                    for (DateTime date = tuNgay; date <= denNgay2; date = date.AddDays(1))
                    {
                        if ((((byte)congViecBan.ThuTrongTuan & (byte)x.ThuTrongTuan) > 0) && (((byte)congViecBan.Buoi & (byte)x.Buoi) > 0))
                            throw new Exception(string.Format("Giảng viên bận {0} vào {1} trong {2}",
                                congViecBan.NoiDungBan, congViecBan.ThứTrongTuầnString, congViecBan.KhoảngThờiGianString));
                    }
                }

                // Dạng 2
                lstCongViecBan = db.CongViecBanGiangVienDbSet.Where(e => e.MaGiangVien == maGiangVien && e.MaHocKyGUID == maHocKyGUID &&
                    tuNgay <= e.TuNgay && e.DenNgay <= denNgay && e.CongViecBanGiangVienGUID != congViecBanGiangVienGUID).ToList();
                foreach (var congViecBan in lstCongViecBan)
                {
                    // Kiểm tra xem (buoi, thuTrongTuan trong khoảng [tuNgay, denNgay] có xung đột với congViecBan hay không
                    for (DateTime date = congViecBan.TuNgay; date <= congViecBan.DenNgay; date = date.AddDays(1))
                    {
                        if ((((byte)congViecBan.ThuTrongTuan & (byte)x.ThuTrongTuan) > 0) && (((byte)congViecBan.Buoi & (byte)x.Buoi) > 0))
                            throw new Exception(string.Format("Giảng viên bận {0} vào {1} trong {2}",
                                congViecBan.NoiDungBan, congViecBan.ThứTrongTuầnString, congViecBan.KhoảngThờiGianString));
                    }
                }

                // Dạng 3
                lstCongViecBan = db.CongViecBanGiangVienDbSet.Where(e => e.MaGiangVien == maGiangVien && e.MaHocKyGUID == maHocKyGUID &&
                    e.TuNgay <= denNgay && denNgay <= e.DenNgay && e.CongViecBanGiangVienGUID != congViecBanGiangVienGUID).ToList();
                foreach (var congViecBan in lstCongViecBan)
                {
                    // Kiểm tra xem (buoi, thuTrongTuan trong khoảng [tuNgay, denNgay] có xung đột với congViecBan hay không
                    var tuNgay2 = maxOf(tuNgay, congViecBan.TuNgay);
                    for (DateTime date = tuNgay2; date <= denNgay; date = date.AddDays(1))
                    {
                        if ((((byte)congViecBan.ThuTrongTuan & (byte)x.ThuTrongTuan) > 0) && (((byte)congViecBan.Buoi & (byte)x.Buoi) > 0))
                            throw new Exception(string.Format("Giảng viên bận {0} vào {1} trong {2}",
                                congViecBan.NoiDungBan, congViecBan.ThứTrongTuầnString, congViecBan.KhoảngThờiGianString));
                    }
                }
                #endregion

                #region Kiểm tra xem giảng viên có bận giảng dạy SĐH trong khoảng thời gian định thêm mới không?
                var lstTKB = db.LopHocPhan_ThoiKhoaBieuDbSet.Where(e => e.MaGiangVien == maGiangVien && tuNgay <= e.NgayHoc && e.NgayHoc <= denNgay).ToList();
                foreach (var tkb in lstTKB)
                {
                    var iThuTrongTuan = 1 << (byte)BizThoiKhoaBieu.GetIndexFromDOW(tkb.NgayHoc.DayOfWeek);
                    var iBuoiHoc = 1 << (byte)tkb.BuoiHoc;
                    var lhp = BizLopHocPhan.GetByID(tkb.MaLopHocPhanGUID);
                    if (((byte)x.ThuTrongTuan & iThuTrongTuan) > 0 && ((byte)x.Buoi & iBuoiHoc) > 0)
                        throw new Exception(string.Format("Giảng viên bận dạy SĐH vào {0} {1} ngày {2} (lớp {3})",
                            BizThoiKhoaBieu.GetStringOfBuoi(tkb.BuoiHoc),
                            BizThoiKhoaBieu.GetThuTrongTuan(tkb.NgayHoc), tkb.NgayHoc.ToString("dd/MM/yyyy"), lhp.TenLopHocPhan));
                }
                #endregion

                #region Kiểm tra xem giảng viên có bận giảng dạy ĐH trong khoảng thời gian định thêm mới không?
                try
                {
                    using (var db2 = CEMS_DHKH.Models.CEMS_DHKhoaHocContext.GetContext())
                    {
                        var lstTKB2 = db2.ThoiKhoaBieuDaoTaoDaiHocDbSet.Where(e => e.MaGiangVien == maGiangVien && tuNgay <= e.NgayHoc && e.NgayHoc <= denNgay).ToList();
                        foreach (var tkb in lstTKB)
                        {
                            var iThuTrongTuan = 1 << (byte)BizThoiKhoaBieu.GetIndexFromDOW(tkb.NgayHoc.DayOfWeek);
                            var iBuoiHoc = 1 << (byte)tkb.BuoiHoc;
                            if (((byte)x.ThuTrongTuan & iThuTrongTuan) > 0 && ((byte)x.Buoi & iBuoiHoc) > 0)
                                throw new Exception(string.Format("Giảng viên bận dạy ĐH vào {0} {1} ngày {2}",
                                    BizThoiKhoaBieu.GetStringOfBuoi(tkb.BuoiHoc),
                                    BizThoiKhoaBieu.GetThuTrongTuan(tkb.NgayHoc), tkb.NgayHoc.ToString("dd/MM/yyyy")));
                        }
                    }
                }
                catch { }
                #endregion

                BizNhatKyHoatDong.LogAndCommitUpdate(oldX, x, x.CongViecBanGiangVienGUID, LOAIDOITUONG.CÔNG_VIỆC_BẬN_CỦA_GV, db);
            }
        }

        internal static void Delete(string congViecBanGiangVienGUID, CEMS4UG_DHKHContext db = null)
        {
            if (db == null)
                using (var db2 = CEMS4UG_DHKHContext.GetContext())
                    Delete(congViecBanGiangVienGUID, db2);
            else
            {
                var x = db.CongViecBanGiangVienDbSet.Where(e => e.CongViecBanGiangVienGUID == congViecBanGiangVienGUID).FirstOrDefault();
                if (x == null)
                    throw new Exception("Mục công việc bận của giảng viên không còn tồn tại trên hệ thống");
                db.CongViecBanGiangVienDbSet.Remove(x);
                BizNhatKyHoatDong.LogAndCommitDelete2(x, x.CongViecBanGiangVienGUID, LOAIDOITUONG.CÔNG_VIỆC_BẬN_CỦA_GV, db);
            }
        }
    }
}
